package com.adee.jdk8;

import java.util.Arrays;
import java.util.List;
import java.util.function.BiFunction;
import java.util.function.Function;

/*
* jdk中自带的集中函数式接口之Function
* interface Function<T,R> 表示一种函数操作：接收一个T类型的参数，返回一个R类型的值。
*
*
* jdk1.8中在java.util.function包下定义了一系列函数式接口，总结起来，分为四类：
* Consumer（消费型），一个参数，无返回值；
*   如：Consumer<T>
* Supplier（生产型），无参数，有返回值；
*   如：Supplier<T>
* Function（功能型），有参数，有返回值；
*   如：Function<T,R>，BiFunction<>
* Predicate（断言型），有参数，返回值为boolean；
*   如：Predicate<T>
*
* */
public class Test003_Function {
    public static void main(String[] args) {
        // test1();
        // test2();
        test3();
    }

    public static void test1() {
        Function<String, Integer> fun = Integer::parseInt; // 定义一个函数式接口的对象
        System.out.println(fun.getClass().getInterfaces()[0]); // interface java.util.function.Function
        handleStr("128", fun);
        handleStr("hello", t -> t==null ? "null" : t +" 😊");
    }

    // 定义一个应用：原料是一个字符串（第一个参数），操作是自定义的（第二个参数）
    public static <R> R handleStr(String s, Function<String,R> fun) {
        R r = fun.apply(s);
        System.out.println(r);
        return r;
    }

    // Function接口的链式操作
    public static void test2() {
        // 定义一组链式操作，字符串 => 转为数字 => 加上100 => 转为字符串 => 加上😊
        Function<Object, String> fun =
                Function.identity()
                        .andThen(s -> Integer.parseInt((String)s))
                        .andThen(i -> i + 100)
                        .andThen(String::valueOf)
                        .andThen(s -> s + " 😊");

        System.out.println(fun.apply("1997")); // 2097 😊
    }

    // BiFunction<T,U,R>两个参数的功能型接口，T为第一个参数类型，U为第二个参数类型，R为第三个参数类型
    public static void test3() {
        // 给定一个字符串列表，将其转为数字并求和
        List<String> list = Arrays.asList("1", "12", "15", "8", "22");
        BiFunction<String, Integer, Integer> fun = (s, i) -> Integer.parseInt(s) + i;
        // reduce
        final int[] sum = {0};
        list.forEach(s -> sum[0] = fun.apply(s, sum[0]));
        System.out.println("sum" + list + "=" + sum[0]);

        Integer sum2 = list.stream().map(Integer::parseInt).reduce(0, (i, j) -> i + j);
        System.out.println("sum2=" + sum2);
    }
}
